/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "wifi_device_util.h"

#include <stdio.h>

#include "cmsis_os.h"
#include "samgr/common.h"
#include "ohos_init.h"

#include "wifi_hotspot_config.h"

#define WIFI_WAIT_FOREVER 0xFFFFFFFF
#define CHANNEL_80211B_ONLY 14
#define FREQ_OF_CHANNEL_1 2412
#define FREQ_OF_CHANNEL_80211B_ONLY 2484
#define WIFI_MIN_CHANNEL 1
#define WIFI_FREQ_INTERVAL 5

static MutexId g_wifiGlobalLock = NULL;
static MutexId g_wifiEventLock = NULL;

WifiSecurityType HiSecToHoSec(xr_wifi_auth_mode mode)
{
	switch (mode) {
	case XR_WIFI_SECURITY_OPEN:
		return WIFI_SEC_TYPE_OPEN;
	case XR_WIFI_SECURITY_WEP:
		return WIFI_SEC_TYPE_WEP;
	case XR_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX:
	case XR_WIFI_SECURITY_WPAPSK:
	case XR_WIFI_SECURITY_WPA2PSK:
		return WIFI_SEC_TYPE_PSK;
	case XR_WIFI_SECURITY_SAE:
		return WIFI_SEC_TYPE_SAE;
	default:
		return WIFI_SEC_TYPE_INVALID;
	}
}

xr_wifi_auth_mode HoSecToHiSec(WifiSecurityType type)
{
	switch (type) {
	case WIFI_SEC_TYPE_OPEN:
		return XR_WIFI_SECURITY_OPEN;
	case WIFI_SEC_TYPE_WEP:
		return XR_WIFI_SECURITY_WEP;
	case WIFI_SEC_TYPE_PSK:
		return XR_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX;
	case WIFI_SEC_TYPE_SAE:
		return XR_WIFI_SECURITY_SAE;
	default:
		return XR_WIFI_SECURITY_UNKNOWN;
	}
}

void InitWifiGlobalLock(void)
{
	if (g_wifiGlobalLock == NULL) {
		osMutexAttr_t globalMutexAttr = { "WifiGloablLock",
						  osMutexRecursive |
							  osMutexPrioInherit,
						  NULL, 0U };
		g_wifiGlobalLock = osMutexNew(&globalMutexAttr);
	}

	if (g_wifiEventLock == NULL) {
		osMutexAttr_t eventMutexAttr = { "WifiEventLock",
						 osMutexRecursive |
							 osMutexPrioInherit,
						 NULL, 0U };
		g_wifiEventLock = osMutexNew(&eventMutexAttr);
	}
}

WifiErrorCode LockWifiGlobalLock(void)
{
	if (g_wifiGlobalLock == NULL) {
		return ERROR_WIFI_UNKNOWN;
	}

	osStatus_t ret = osMutexAcquire(g_wifiGlobalLock, WIFI_WAIT_FOREVER);
	if (ret != osOK) {
		printf("[wifi_service] osMutexAcquire failed \n");
		return ERROR_WIFI_UNKNOWN;
	}

	return WIFI_SUCCESS;
}

WifiErrorCode UnlockWifiGlobalLock(void)
{
	if (g_wifiGlobalLock == NULL) {
		return ERROR_WIFI_UNKNOWN;
	}

	osStatus_t ret = osMutexRelease(g_wifiGlobalLock);
	if (ret != osOK) {
		printf("[wifi_service] osMutexUnlock failed \n");
		return ERROR_WIFI_UNKNOWN;
	}

	return WIFI_SUCCESS;
}

WifiErrorCode LockWifiEventLock(void)
{
	if (g_wifiEventLock == NULL) {
		return ERROR_WIFI_UNKNOWN;
	}

	osStatus_t ret = osMutexAcquire(g_wifiEventLock, WIFI_WAIT_FOREVER);
	if (ret != osOK) {
		printf("[wifi_service] osMutexAcquire event failed \n");
		return ERROR_WIFI_UNKNOWN;
	}

	return WIFI_SUCCESS;
}

WifiErrorCode UnlockWifiEventLock(void)
{
	if (g_wifiEventLock == NULL) {
		return ERROR_WIFI_UNKNOWN;
	}

	osStatus_t ret = osMutexRelease(g_wifiEventLock);
	if (ret != osOK) {
		printf("[wifi_service] osMutexUnlock event failed \n");
		return ERROR_WIFI_UNKNOWN;
	}

	return WIFI_SUCCESS;
}

unsigned int ChannelToFrequency(unsigned int channel)
{
	if (channel <= 0) {
		return 0;
	}

	if (channel == CHANNEL_80211B_ONLY) {
		return FREQ_OF_CHANNEL_80211B_ONLY;
	}
	return (((channel - WIFI_MIN_CHANNEL) * WIFI_FREQ_INTERVAL) +
		FREQ_OF_CHANNEL_1);
}

unsigned int FrequencyToChannel(unsigned int frequency)
{
	if (frequency == FREQ_OF_CHANNEL_80211B_ONLY) {
		return CHANNEL_80211B_ONLY;
	}

	if (frequency < FREQ_OF_CHANNEL_1) {
		return 0;
	}

	return (frequency - FREQ_OF_CHANNEL_1) / WIFI_FREQ_INTERVAL +
	       WIFI_MIN_CHANNEL;
}

CORE_INIT(InitWifiGlobalLock);
